#include "db_conninfo.h"
#include "opengauss/libpq-fe.h"
#include <unordered_map>
#include <vector>
#include <regex>
#include <string>

std::string GetsShemanameTablenamesql = "select schemaname,tablename from pg_tables where schemaname <> 'db4ai'"
                                        " AND schemaname <>'snapshot' AND schemaname <>'pg_catalog'"
                                        " AND schemaname <>'information_schema' AND schemaname <>'dbe_pldeveloper' AND schemaname<>'coverage';";

int GetsShemanameTablename(PGconn *conn, const char *sql, std::unordered_map<std::string, std::string> &configMap)
{
    int nFields;
    int i, j;

    // 执行查询语句
    PGresult *res = PQexec(conn, sql);
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "查询失败: %s", PQerrorMessage(conn));
        PQclear(res);
        PQfinish(conn);
        return 1;
    }

    // 获取结果集中的行数
    int rows = PQntuples(res);
    nFields = PQnfields(res);
    /* 打印行 */
    char result[1024];
    for (j = 0; j < nFields; j++)
    {
        // 获取你需要的两个字段的列索引，假设需要 column2 和 column4
        int column_index1 = PQfnumber(res, "\"schemaname\"");
        int column_index2 = PQfnumber(res, "\"tablename\"");
        if (column_index1 == -1 || column_index2 == -1)
        {
            fprintf(stderr, "未找到指定的列\n");
            PQclear(res);
            PQfinish(conn);
            return 1;
        }

        // 遍历结果集，获取所需两个字段的值
        for (int i = 0; i < rows; i++)
        {
            const char *value1 = PQgetvalue(res, i, column_index1);
            const char *value2 = PQgetvalue(res, i, column_index2);
            // printf("第 %d 行: Schema 的值为 %s, Name 的值为 %s\n", i + 1, value1, value2);
            std::string keys = std::string(value1) + "|" + std::string(value2);
            configMap[keys] = value2;
        }
    }

    // 释放结果集和关闭数据库连接
    PQclear(res);
    // PQfinish(conn);
    return 0;
}

std::vector<std::string> split(const std::string &s, char delimiter)
{
    std::vector<std::string> tokens;
    std::string token;
    std::istringstream tokenStream(s);
    // 按分隔符拆分字符串
    while (std::getline(tokenStream, token, delimiter))
    {
        tokens.push_back(token);
    }
    return tokens;
}

std::string buildSQLQuery(const std::string& table, 
                         const std::vector<std::pair<std::string, std::string>>& conditions) {
    std::string query = "SELECT * FROM " + table;
    if (!conditions.empty()) {
        query += " WHERE ";
        for (size_t i = 0; i < conditions.size(); ++i) {
            query += conditions[i].first + " = '" + conditions[i].second + "'";
            if (i < conditions.size() - 1) {
                query += " AND ";
            }
        }
    }
    return query;
}


std::string buildSQLQuery(const std::string& schema, const std::string& table) {
    std::string query = "SELECT string_agg(a.attname,',') as indexcolumn,c.relname as indexname,"
    "c2.relname as tablename,n.nspname as \"Schema\", n.nspname||'.'||c.relname as allpathindexname,"
    "pg_size_pretty(pg_relation_size(allpathindexname)),pg_relation_size(allpathindexname) FROM "
    "pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) JOIN "
    "pg_catalog.pg_class c ON i.indexrelid = c.oid JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid "
    "JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace where i.indisprimary is not true and i.indisunique "
    "is not true and n.nspname <> 'pg_catalog' AND n.nspname <> 'db4ai' AND n.nspname <> 'information_schema' AND "
    "n.nspname <> 'dbe_pldeveloper' AND n.nspname !~ '^pg_toast' and n.nspname='"+ schema + "'" 
    "and c2.relname='"+ table + "'"
    " group by n.nspname,c2.relname,c.relname order by pg_relation_size desc;";
    return query;
}
